#include <iostream>
#include <websocketpp/server.hpp>
#include <websocketpp/config/asio_no_tls.hpp>
#include <functional>
#include <string>

typedef websocketpp::server<websocketpp::config::asio> webserver;

// 握手成功回调函数
void open_hander(webserver *w1, websocketpp::connection_hdl hd)
{
    std::cout << "websocketpp 握手成功!\n";
}

// 连接关闭回调函数
void close_hander(webserver *w1, websocketpp::connection_hdl hd)
{
    std::cout << "websocketpp 连接断开!\n";
}

// 消息处理回调函数
void message_hander(webserver *w1, websocketpp::connection_hdl hd, webserver::message_ptr ms)
{
    webserver::connection_ptr con = w1->get_con_from_hdl(hd);
    std::cout << "msg: " << ms->get_payload() << std::endl;
    // 返回客户端
    std::string resp = "client say: " + ms->get_payload();
    con->send(resp, websocketpp::frame::opcode::text);
}

// http请求回调函数
void http_hander(webserver *w1, websocketpp::connection_hdl hd)
{
    // 客户端http请求过来，处理http请求   获取 connection_hd1 中对应的连接的 connetion_ptr
    webserver::connection_ptr con = w1->get_con_from_hdl(hd);
    // 获取请求正文
    std::cout << "http request body: " << con->get_request_body() << std::endl;
    // 获取请求对象
    websocketpp::http::parser::request req = con->get_request();
    std::cout << "http request method: " << req.get_method() << std::endl;
    std::cout << "http request uri: " << req.get_uri() << std::endl;

    // 构建http响应
    std::string body = "<html><body><h1> Hello World </h1></body></html>";
    con->set_body(body);                             // 正文
    con->append_header("Content-Type", "text/html"); // 头部
    con->set_status(websocketpp::http::status_code::ok);
}
int main()
{
    // 1、实例化server对象
    webserver wsserver;
    // 2、设置日志等级  禁止打印所有日志等级
    wsserver.set_access_channels(websocketpp::log::alevel::none);
    // 3、初始化 asio 框架调度器
    wsserver.init_asio();
    wsserver.set_reuse_addr(true); // 地址复用
    // 4、设置业务处理回调函数  收到那个消息就调用哪个
    wsserver.set_http_handler(std::bind(http_hander, &wsserver, std::placeholders::_1));
    wsserver.set_open_handler(std::bind(open_hander, &wsserver, std::placeholders::_1)); // 哪个函数，什么参数
    wsserver.set_close_handler(std::bind(close_hander, &wsserver, std::placeholders::_1));
    wsserver.set_message_handler(std::bind(message_hander, &wsserver, std::placeholders::_1, std::placeholders::_2));
    // 5、设置服务器监听端口号
    wsserver.listen(8086);
    // 6、开始获取新连接
    wsserver.start_accept();
    // 7、运行服务器
    wsserver.run();
    return 0;
}